package cn.geminis.lowcode.processor;

import cn.geminis.lowcode.compiler.Context;
import cn.geminis.lowcode.utils.SourceFileContext;
import cn.geminis.lowcode.utils.Utils;
import com.google.auto.service.AutoService;

import javax.annotation.processing.*;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.TypeElement;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author puddi
 */
@AutoService(Processor.class)
@SupportedAnnotationTypes({
        "cn.geminis.lowcode.annotation.UuidEntity",
        "cn.geminis.lowcode.annotation.SoftDeleteEntity",
        "cn.geminis.lowcode.annotation.CrudRepository",
        "cn.geminis.lowcode.annotation.QueryFilter",
        "cn.geminis.lowcode.annotation.CrudController",
        "cn.geminis.lowcode.annotation.GeminisApplication"
})
public class LcProcessor extends AbstractProcessor {

    @Override
    public synchronized void init(ProcessingEnvironment processingEnv) {
        Context.INSTANCE.init(processingEnv);
        super.init(processingEnv);
        Utils.noteMessage("LowCode Processor Initialed");
    }

    @Override
    public Set<String> getSupportedAnnotationTypes() {
        return ProcessorManager.getProcessors()
                .stream().map(processor -> processor.getSupportAnnotation().getName())
                .collect(Collectors.toSet());
    }

    @Override
    public SourceVersion getSupportedSourceVersion() {
        return SourceVersion.latestSupported();
    }

    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        if (annotations.isEmpty()) {
            return false;
        }

        ProcessorManager.getProcessors()
                .forEach(processor -> {
                    roundEnv.getElementsAnnotatedWith(processor.getSupportAnnotation())
                            .forEach(processor::process);
                });

        SourceFileContext.generateSourceFile();

        return false;
    }
}
